import mysql from 'mysql2/promise';
import { dbConfig } from '../config/dbConfig.js';

// ✅ 创建连接池
// ...是什么
// 这是 JavaScript 的对象展开运算符（Spread Operator）
// 它会把 dbConfig 对象里面的属性全部展开到新的对象里
//waitForConnections : 当连接池已满时，是否等待可用连接。如果为 false，超过连接数会直接报错
//connectionLimit :  最大连接数，控制同时最多允许多少个连接存在池中
//queueLimit :  队列限制，0 表示无限制，连接请求会排队等待
//注意： 连接池能提高性能，避免每次查询都新建连接。
const pool = mysql.createPool({
    ...dbConfig,
    waitForConnections: true,
    connectionLimit: 10,
    queueLimit: 0
});

/*
---------------------------
基础查询方法
说明
    作用：执行 查询（SELECT），返回查询结果数组
    参数：
        sql：SQL 字符串，例如 'SELECT * FROM users WHERE id = ?'
        params：数组，对应 SQL 中的占位符 ?
    返回值：
        Promise，解析为 rows 数组
    注意事项：
        使用参数化查询，防止 SQL 注入
        如果 SQL 错误，会抛出异常
    示例：
        const users = await db.query('SELECT * FROM users WHERE age > ?', [18]);
---------------------------
* */
async function query(sql, params = []) {
    try {
        const [rows] = await pool.execute(sql, params);
        return rows;
    } catch (err) {
        console.error('[DB QUERY ERROR]', err, sql, params);
        throw err;
    }
}


/*
---------------------------
 基础执行方法（增删改）
 说明
    作用：
        执行 增删改（INSERT/UPDATE/DELETE） 操作
    参数：
        sql：SQL 字符串
        params：占位符参数数组
    返回值：
        Promise，解析为 MySQL 的结果对象，包含 affectedRows、insertId 等
    注意事项：
        如果需要多条操作原子执行，建议使用 transaction

    示例：
        const result = await db.execute('UPDATE users SET name = ? WHERE id = ?', ['Tom', 1]);
        console.log(result.affectedRows); // 更新行数
---------------------------
*/
async function execute(sql, params = []) {
    try {
        const [result] = await pool.execute(sql, params);
        return result;
    } catch (err) {
        console.error('[DB EXECUTE ERROR]', err, sql, params);
        throw err;
    }
}


/*
---------------------------
 事务操作
 说明
    作用：封装事务，保证多条 SQL 原子性
    参数：
        callback：一个 async 函数，参数为事务连接 conn
        在 callback 内可以执行多条 SQL：await conn.execute(...)
    返回值：
        callback 的返回值
    使用场景：
        多条操作必须成功或失败一起回滚

    示例：
        await db.transaction(async (conn) => {
              await conn.execute('UPDATE accounts SET balance = balance - ? WHERE id = ?', [100, 1]);
              await conn.execute('UPDATE accounts SET balance = balance + ? WHERE id = ?', [100, 2]);
            });
---------------------------
 */
async function transaction(callback) {
    const connection = await pool.getConnection();
    try {
        await connection.beginTransaction();
        const result = await callback(connection);
        await connection.commit();
        return result;
    } catch (err) {
        await connection.rollback();
        console.error('[DB TRANSACTION ERROR]', err);
        throw err;
    } finally {
        connection.release();
    }
}

/*
 ---------------------------
 批量操作（自动分批）
 说明
     作用：
        批量新增数据，自动分批，防止 SQL 太大
    参数：
        table：表名
        columns：列名数组 ['col1','col2']
        data：二维数组 [[val1,val2],[val3,val4]]
        batchSize：每批插入数量，默认 500
    示例：
        await db.batchInsert('users', ['name', 'age'], [  ['Alice', 20],   ['Bob', 25] ]);
    优化点：
        自动拆分批次，防止占位符过多
        使用单条 SQL 多值插入，性能高


---------------------------
 */
async function batchInsert(table, columns, data, batchSize = 500) {
    if (!data || data.length === 0) return;

    const colStr = columns.map(c => `\`${c}\``).join(',');
    for (let i = 0; i < data.length; i += batchSize) {
        const batch = data.slice(i, i + batchSize);
        const placeholders = batch.map(row => `(${row.map(() => '?').join(',')})`).join(',');
        const flatValues = batch.flat();
        const sql = `INSERT IGNORE INTO \`${table}\` (${colStr}) VALUES ${placeholders}`;
        await execute(sql, flatValues);
    }
}

/* ---------------------------
    批量删除
    作用：按主键或指定列批量删除
    参数：
        table：表名
        keyColumn：删除条件列名（通常是 id）
        ids：要删除的值数组 [1,2,3]
        batchSize：每批数量
    示例：
        await db.batchDelete('users', 'id', [1,2,3,4,5]);

 */
async function batchDelete(table, keyColumn, ids, batchSize = 500) {
    if (!ids || ids.length === 0) return;

    for (let i = 0; i < ids.length; i += batchSize) {
        const batch = ids.slice(i, i + batchSize);
        const placeholders = batch.map(() => '?').join(',');
        const sql = `DELETE FROM \`${table}\` WHERE \`${keyColumn}\` IN (${placeholders})`;
        await execute(sql, batch);
    }
}

/*
---------------------------
 说明
    作用：批量更新多条记录
    参数：
        table：表名
        keyColumn：更新条件列名（通常是 id）
        data：数组，每个元素是对象，例如 [{id:1, name:'Tom'},{id:2, name:'Jerry'}]
        batchSize：每批处理数量，默认 100
    实现方式：
        使用 CASE WHEN 构建 SQL，一条 SQL 更新多条记录
    示例：
        await db.batchUpdate('users', 'id', [
          {id: 1, name: 'Tom', age: 21},
          {id: 2, name: 'Jerry', age: 22}
        ]);

 */
async function batchUpdate(table, keyColumn, data, batchSize = 100) {
    if (!data || data.length === 0) return;

    for (let i = 0; i < data.length; i += batchSize) {
        const batch = data.slice(i, i + batchSize);

        // 构建 CASE WHEN SQL
        const columns = Object.keys(batch[0]).filter(c => c !== keyColumn);
        const cases = columns.map(col => {
            const caseStr = batch.map(row => `WHEN ${row[keyColumn]} THEN ?`).join(' ');
            return `\`${col}\` = CASE \`${keyColumn}\` ${caseStr} ELSE \`${col}\` END`;
        }).join(', ');

        const sql = `UPDATE \`${table}\` SET ${cases} WHERE \`${keyColumn}\` IN (${batch.map(r => r[keyColumn]).join(',')})`;

        // 参数顺序对应 CASE WHEN
        const params = [];
        columns.forEach(col => {
            batch.forEach(row => {
                params.push(row[col]);
            });
        });

        await execute(sql, params);
    }
}


// mysql.js
export default {
    query,
    execute,
    transaction,
    batchInsert,
    batchDelete,
    batchUpdate
};
